package com.maxdu.labs.stt.models.db;

import java.util.ArrayList;
import java.util.List;

import android.util.Log;

import com.maxdu.labs.stt.constants.Constants;
import com.maxdu.labs.stt.constants.FriendRequestConstants;
import com.maxdu.labs.stt.models.FriendRequest;
import com.parse.FindCallback;
import com.parse.GetCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.SaveCallback;

 public class FriendRequestDBHelper {
	public final static String PARSE_DB_TABLENAME_FRIENDREQUESTS = "FriendRequestParseObject";
	public final static String PARSE_DB_FIELD_SENDERID = "senderId";
	public final static String PARSE_DB_FIELD_RECEIVERID = "ReceiverId";
	public final static String PARSE_DB_FIELD_ACCEPTED = "accepted";
	public final static String PARSE_DB_FIELD_RESPONSE_DATE = "reponseDate";
	private ParseObject friendRequestParseObject;
	private FriendRequest friendRequest;
	
	
	public FriendRequestDBHelper(){
		friendRequestParseObject = new ParseObject (PARSE_DB_TABLENAME_FRIENDREQUESTS);
	}
	
	public void saveToCloud(FriendRequest argFR){
		
		this.friendRequest = argFR;
		
		if(friendRequest != null){
			friendRequestParseObject.put(PARSE_DB_FIELD_SENDERID, argFR.getUserSenderId());
			friendRequestParseObject.put(PARSE_DB_FIELD_RECEIVERID, argFR.getUserReceiverId());
			friendRequestParseObject.put(PARSE_DB_FIELD_ACCEPTED, argFR.getAccepted());
			if (argFR.getResponseDate() != null){
				friendRequestParseObject.put(PARSE_DB_FIELD_RESPONSE_DATE, argFR.getResponseDate());
			}
			friendRequestParseObject.saveInBackground(new SaveCallback() {
				
				@Override
				public void done(ParseException e) {
					if (e == null){
						Log.d(Constants.LOG_TAG, "we successfully updated to Cloud the friendRequest between [" + friendRequest.getUserSenderId() + "] and ["+ friendRequest.getUserReceiverId() + "]");
					}else{
						Log.w(Constants.LOG_TAG, "PROBLEM when trying to update friendRequest between [" + friendRequest.getUserSenderId() + "] and ["+ friendRequest.getUserReceiverId() + "] errorMessage:: " + e);
						//TODO manage the unicity in Cloud Code so you can't enter twice a FR
					}
					
				}
			});
		}else{
			Log.e(Constants.LOG_TAG, "UserDBHelper::updateToCloud() :: USER IS NULL");
		}
	}
	
	public FriendRequest getFriendRequestFromCloud(String senderId, String receiverId){
		
		//TODO clean this sh**... sure there is a better way to do so!
		
		ParseQuery<ParseObject> queryPart1 = ParseQuery.getQuery(PARSE_DB_TABLENAME_FRIENDREQUESTS);
		queryPart1.whereEqualTo(PARSE_DB_FIELD_SENDERID, senderId);
		queryPart1.whereEqualTo(PARSE_DB_FIELD_RECEIVERID, receiverId);
		
		ParseQuery<ParseObject> queryPart2 = ParseQuery.getQuery(PARSE_DB_TABLENAME_FRIENDREQUESTS);
		queryPart1.whereEqualTo(PARSE_DB_FIELD_SENDERID, receiverId);
		queryPart1.whereEqualTo(PARSE_DB_FIELD_RECEIVERID, senderId);
		
		List<ParseQuery<ParseObject>> fullQuery = new ArrayList<ParseQuery<ParseObject>>();
		fullQuery.add(queryPart1);
		fullQuery.add(queryPart2);
		
		ParseQuery.or(fullQuery).getFirstInBackground(new GetCallback<ParseObject>() {
			@Override
            public void done(ParseObject friendRequestParseObject, ParseException e) {
		        if (e == null) {
		        	friendRequest = populateFriendRequest(friendRequestParseObject);
		        	Log.d(Constants.LOG_TAG, "we successfully retrieved from Cloud the friendRequest : between [" + friendRequest.getUserSenderId() + "] and ["+ friendRequest.getUserReceiverId() + "]");
		        } else {
		            Log.d(Constants.LOG_TAG, "we couldn't retrieve from Cloud the friendRequest : between [" + friendRequest.getUserSenderId() + "] and ["+ friendRequest.getUserReceiverId() + "] Error: " + e.getMessage());
		        }
		    }
		});
		
		return friendRequest;
	}
	
	//TODO refactor this method with the getFriendRequestFromCloud one
	public ParseObject getParseObjectFriendRequestFromCloud(String senderId, String receiverId){
		
		ParseQuery<ParseObject> queryPart1 = ParseQuery.getQuery(PARSE_DB_TABLENAME_FRIENDREQUESTS);
		queryPart1.whereEqualTo(PARSE_DB_FIELD_SENDERID, senderId);
		queryPart1.whereEqualTo(PARSE_DB_FIELD_RECEIVERID, receiverId);
		
		ParseQuery<ParseObject> queryPart2 = ParseQuery.getQuery(PARSE_DB_TABLENAME_FRIENDREQUESTS);
		queryPart1.whereEqualTo(PARSE_DB_FIELD_SENDERID, receiverId);
		queryPart1.whereEqualTo(PARSE_DB_FIELD_RECEIVERID, senderId);
		
		List<ParseQuery<ParseObject>> fullQuery = new ArrayList<ParseQuery<ParseObject>>();
		fullQuery.add(queryPart1);
		fullQuery.add(queryPart2);
		
		ParseQuery.or(fullQuery).getFirstInBackground(new GetCallback<ParseObject>() {
			@Override
            public void done(ParseObject friendRequestParseObjectLocal, ParseException e) {
		        if (e == null) {
		        	friendRequestParseObject = friendRequestParseObjectLocal;
		        	Log.w(Constants.LOG_TAG,"current Object id === " + friendRequestParseObject.getObjectId()); 
		        	Log.d(Constants.LOG_TAG, "we successfully retrieved from Cloud the friendRequest : between [" + friendRequestParseObject.getString(PARSE_DB_FIELD_SENDERID) + "] and ["+ friendRequestParseObject.getString(PARSE_DB_FIELD_RECEIVERID) + "]");
		        } else {
		            Log.d(Constants.LOG_TAG, "we couldn't retrieve from Cloud the friendRequest : between [" + friendRequestParseObject.getString(PARSE_DB_FIELD_SENDERID) + "] and ["+ friendRequestParseObject.getString(PARSE_DB_FIELD_RECEIVERID) + "] Error: " + e.getMessage());
		        }
		    }
		});
		
		return friendRequestParseObject;
	}
	
	public static List<FriendRequest> getFriendRequestsOfAUser(String userId){
		ParseQuery<ParseObject> query = ParseQuery.getQuery(PARSE_DB_TABLENAME_FRIENDREQUESTS);
		query.whereEqualTo(PARSE_DB_FIELD_RECEIVERID, userId);
		query.whereEqualTo(PARSE_DB_FIELD_ACCEPTED, FriendRequestConstants.FRIEND_REQUEST_PENDING);
		
		Log.w(Constants.LOG_TAG, "****************************************************");
		Log.w(Constants.LOG_TAG, "receiverId == " + userId);
		Log.w(Constants.LOG_TAG, "****************************************************");
		
		final List<FriendRequest> friendRequests = new ArrayList<FriendRequest>();
		
		Log.d(Constants.LOG_TAG, "getFriendRequestsOfAUser:: About to try to get the friendRequests received by this user: " + userId);
		
		query.findInBackground(new FindCallback<ParseObject>() {
		    public void done(List<ParseObject> friendRequestList, ParseException e) {
		        if (e == null) {
		        	if (friendRequestList != null && friendRequestList.size()> 0){
		        		for (ParseObject userParseObject : friendRequestList){
		        			FriendRequest friendRequest = new FriendRequest(userParseObject.getString(PARSE_DB_FIELD_SENDERID), userParseObject.getString(PARSE_DB_FIELD_RECEIVERID));
		        			friendRequests.add(friendRequest);
		        		}
		        		Log.d(Constants.LOG_TAG, "we successfully retrieved [" + friendRequestList.size()+"] pending FriendRequests for the user: " + friendRequestList.get(0).getString(PARSE_DB_FIELD_RECEIVERID));
		        	}else if(friendRequestList == null){
		        		Log.d(Constants.LOG_TAG, "we couldn't retrieve the pending FriendRequests for the current user: users list is NULL");
		        	}else{
		        		Log.d(Constants.LOG_TAG, "we couldn't retrieve the pending FriendRequests for the current user: users list is EMPTY");
		        	}
		        } else {
		            Log.d(Constants.LOG_TAG, "Error: " + e.getMessage());
		        }
		    }
		});
		return friendRequests;
	}
	
	public void acceptFriendRequest(String senderId, String receiverId){
		
		Log.w(Constants.LOG_TAG,"1/ senderId == " + friendRequestParseObject.getString(PARSE_DB_FIELD_SENDERID));
		Log.w(Constants.LOG_TAG,"1/ receiverId == " + friendRequestParseObject.getString(PARSE_DB_FIELD_RECEIVERID));	
		
		ParseQuery<ParseObject> query = ParseQuery.getQuery(PARSE_DB_TABLENAME_FRIENDREQUESTS);
		query.whereEqualTo(PARSE_DB_FIELD_RECEIVERID, receiverId);
		query.whereEqualTo(PARSE_DB_FIELD_SENDERID, senderId);
		query.findInBackground(new FindCallback<ParseObject>() {
		    public void done(List<ParseObject> friendRequestList, ParseException e) {
		        if (e == null) {
		        	if (friendRequestList != null && friendRequestList.size()> 0){
		        		friendRequestParseObject = friendRequestList.get(0);
		        		Log.d(Constants.LOG_TAG, "we successfully retrieved [" + friendRequestList.size()+"] pending FriendRequests for the user: " + friendRequestList.get(0).getString(PARSE_DB_FIELD_RECEIVERID));
	        			
		        		//update the accepted field
		        		friendRequestParseObject.put(PARSE_DB_FIELD_ACCEPTED, FriendRequestConstants.FRIEND_REQUEST_ACCEPTED);
	        			
		        		//save the friend request with the updated field
		        		Log.w(Constants.LOG_TAG, "about to save the ParseObject with ID :: " + friendRequestParseObject.getObjectId());
		        		Log.w(Constants.LOG_TAG,"2/ senderId == " + friendRequestParseObject.getString(PARSE_DB_FIELD_SENDERID));
		        		Log.w(Constants.LOG_TAG,"2/ receiverId == " + friendRequestParseObject.getString(PARSE_DB_FIELD_RECEIVERID));	
		        		friendRequestParseObject.saveInBackground(new SaveCallback() {
	        				
	        				@Override
	        				public void done(ParseException e) {
	        					if (e == null){
	        						Log.d(Constants.LOG_TAG, "we successfully updated to Cloud the friendRequest between [" + friendRequestParseObject.getString(PARSE_DB_FIELD_RECEIVERID) +"] and ["+ friendRequestParseObject.getString(PARSE_DB_FIELD_SENDERID) + "]");
	        					}else{
	        						Log.d(Constants.LOG_TAG, "Error when trying to update to Cloud the friendRequest between [" + friendRequestParseObject.getString(PARSE_DB_FIELD_RECEIVERID) +"] and ["+ friendRequestParseObject.getString(PARSE_DB_FIELD_SENDERID) + "]. Error: " + e);
	        					}
	        					
	        				}
	        			});
		        	}else if(friendRequestList == null){
		        		Log.d(Constants.LOG_TAG, "we couldn't retrieve the pending FriendRequests for the current user: users list is NULL");
		        	}else{
		        		Log.d(Constants.LOG_TAG, "we couldn't retrieve the pending FriendRequests for the current user: users list is EMPTY");
		        	}
		        } else {
		            Log.d(Constants.LOG_TAG, "Error: " + e.getMessage());
		        }
		    }
		});
		/*
		//ParseObject friendRequestWithoutData = ParseObject.createWithoutData(PARSE_DB_TABLENAME_FRIENDREQUESTS, friendRequestParseObject.getObjectId());
		
		if(friendRequestParseObject != null){
			friendRequestParseObject.put(PARSE_DB_FIELD_ACCEPTED, FriendRequestConstants.FRIEND_REQUEST_ACCEPTED);
			
			Log.w(Constants.LOG_TAG, "about to save the ParseObject with ID :: " + friendRequestParseObject.getObjectId());
			
			friendRequestParseObject.saveInBackground(new SaveCallback() {
				
				@Override
				public void done(ParseException e) {
					if (e == null){
						Log.d(Constants.LOG_TAG, "we successfully updated to Cloud the friendRequest between [" + userId +"] and ["+ receiverId + "]");
					}else{
						Log.d(Constants.LOG_TAG, "Error when trying to update to Cloud the friendRequest between [" + userId +"] and ["+ receiverId + "]. Error: " + e);
					}
					
				}
			});
		}else if (userId == null){
			Log.w(Constants.LOG_TAG, "FriendRequestDBHelper::acceptFriendRequest() :: userId IS NULL");
		}else{
			Log.w(Constants.LOG_TAG, "FriendRequestDBHelper::acceptFriendRequest() :: receiverId IS NULL");
		}*/
	}
	
	private FriendRequest populateFriendRequest(ParseObject frPO){
		return new FriendRequest(
				frPO.getString(PARSE_DB_FIELD_SENDERID),
				frPO.getString(PARSE_DB_FIELD_RECEIVERID),
				frPO.getInt(PARSE_DB_FIELD_ACCEPTED),
				frPO.getCreatedAt(),
				frPO.getDate(PARSE_DB_FIELD_RESPONSE_DATE));
	}
}
